package com.qpx.redis.service;

import com.qpx.redis.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.ArrayList;
import java.util.List;

@Service
public class PeopleNearbyService {
    @Autowired
    private RedisTemplate redisTemplate;

    //GEO相关命令用到的KEY
    private final static String KEY = "user_point";

    public boolean save(User user) {
        Long flag = redisTemplate.opsForGeo().add(KEY, new RedisGeoCommands.GeoLocation<>(
                user.getName(),
                new Point(user.getLongitude(), user.getLatitude()))
        );
        boolean result = flag != null && flag > 0;
        return result;
    }

    /**
     * 验证经纬度距离地址：经纬度距离计算 (hhlink.com)
     * 根据当前位置获取附近指定范围内的用户
     *
     * @param distance 指定范围 单位km ，可根据{@link Metrics} 进行设置
     * @param userLng  用户经度
     * @param userLat  用户纬度
     * @return
     */
    public List<User> nearBySearch(double distance, double userLng, double userLat) {
        List<User> users = new ArrayList<>();
        Distance distanceArg = new Distance(distance, Metrics.KILOMETERS);
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                .includeDistance()
                .includeCoordinates().sortAscending();
        // 1.GEORADIUS获取附近范围内的信息
        GeoResults<RedisGeoCommands.GeoLocation<Object>> reslut =
                redisTemplate.opsForGeo().radius(KEY, new Circle(new Point(userLng, userLat), distanceArg), args);
        //2.收集信息，存入list
        List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> content = reslut.getContent();
        //3.返回计算后的信息
        content.forEach(a -> users.add(
                new User().setName(a.getContent().getName().toString())
                        .setDistance(a.getDistance().getValue() * 1000) //因为返回的结果单位与查询参数的一致（km），因此将其扩大为m
                        .setLatitude(a.getContent().getPoint().getX())
                        .setLongitude(a.getContent().getPoint().getY())));
        return users;
    }

    /**
     * 查询指定用户，范围内的用户
     *
     * @param distance
     * @param name
     * @return
     */
    public List<User> searchNearbyName(@RequestParam("distance") double distance, @RequestParam("name") String name) {
        List<User> users = new ArrayList<>();
        List<Point> position = redisTemplate.opsForGeo().position(KEY, name);
        Distance distanceArg = new Distance(distance, Metrics.KILOMETERS);
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                .includeDistance()
                .includeCoordinates().sortAscending();
        // 1.GEORADIUS获取附近范围内的信息
        GeoResults<RedisGeoCommands.GeoLocation<Object>> reslut =
                redisTemplate.opsForGeo().radius(KEY, new Circle(position.get(0), distanceArg), args);
        //2.收集信息，存入list
        List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> content = reslut.getContent();
        //3.返回计算后的信息
        content.forEach(a -> {
            if (!name.equals(a.getContent().getName().toString())) {
                users.add(new User().setName(a.getContent().getName().toString())
                        .setDistance(a.getDistance().getValue() * 1000) //因为返回的结果单位与查询参数的一致（km），因此将其扩大为m
                        .setLatitude(a.getContent().getPoint().getX())
                        .setLongitude(a.getContent().getPoint().getY()));
            }
        });
        return users;
    }
}
